package scatter.comment.rest.hierarchical.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import scatter.comment.pojo.hierarchical.form.CommentHierarchicalStarAddForm;
import scatter.comment.pojo.hierarchical.form.CommentHierarchicalStarPageQueryForm;
import scatter.comment.pojo.hierarchical.form.CommentHierarchicalStarUpdateForm;
import scatter.comment.pojo.hierarchical.param.CommentHierarchicalCancelStarParam;
import scatter.comment.pojo.hierarchical.param.CommentHierarchicalStarAddStarParam;
import scatter.comment.pojo.hierarchical.po.CommentHierarchical;
import scatter.comment.pojo.hierarchical.po.CommentHierarchicalStar;
import scatter.comment.rest.hierarchical.mapper.CommentHierarchicalStarMapper;
import scatter.comment.rest.hierarchical.mapstruct.CommentHierarchicalStarMapStruct;
import scatter.comment.rest.hierarchical.service.ICommentHierarchicalService;
import scatter.comment.rest.hierarchical.service.ICommentHierarchicalStarService;
import scatter.common.pojo.form.BasePageQueryForm;
import scatter.common.rest.service.IBaseAddUpdateQueryFormServiceImpl;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;

/**
 * <p>
 * 评论点赞表 服务实现类
 * </p>
 *
 * @author yw
 * @since 2021-02-09
 */
@Slf4j
@Service
@Transactional
public class CommentHierarchicalStarServiceImpl extends IBaseAddUpdateQueryFormServiceImpl<CommentHierarchicalStarMapper, CommentHierarchicalStar, CommentHierarchicalStarAddForm, CommentHierarchicalStarUpdateForm, CommentHierarchicalStarPageQueryForm> implements ICommentHierarchicalStarService {
    @Qualifier("commonDbTaskExecutor")
    @Autowired
    private ExecutorService executorService;

    @Lazy
    @Autowired
    private ICommentHierarchicalService iCommentHierarchicalService;

    @Override
    public void preAdd(CommentHierarchicalStarAddForm addForm,CommentHierarchicalStar po) {
        super.preAdd(addForm,po);

    }

    @Override
    public void preUpdate(CommentHierarchicalStarUpdateForm updateForm,CommentHierarchicalStar po) {
        super.preUpdate(updateForm,po);

    }


    /**
     * 异步处理添加，该方法永远返回true
     * @param addStartParam
     * @return
     */
    @Override
    public CommentHierarchicalStar addStar(CommentHierarchicalStarAddStarParam addStartParam) {
        CommentHierarchicalStar commentHierarchicalStar = CommentHierarchicalStarMapStruct.INSTANCE.addStartParamToPo(addStartParam);
        commentHierarchicalStar.setTimeAt(LocalDateTime.now());
        commentHierarchicalStar.setFloor(Optional.ofNullable(addStartParam.getFloor()).orElse(1));
        log.info("开始添加一个点赞,commentHierarchicalId={},userId={}",addStartParam.getCommentHierarchicalId(),addStartParam.getOwnerUserId());
        save(commentHierarchicalStar);
        // 添加成功后，点赞数加 1
        iCommentHierarchicalService.plusForColumnById(addStartParam.getCommentHierarchicalId(), CommentHierarchical::getStarCount,1);
        log.info("添加一个点赞结束,commentHierarchicalId={},userId={}",addStartParam.getCommentHierarchicalId(),addStartParam.getOwnerUserId());

        // 更新楼层
        // 如果楼层没传，修正楼层
        if (addStartParam.getFloor() == null) {
            CommentHierarchical byId = iCommentHierarchicalService.getById(addStartParam.getCommentHierarchicalId());
            // 1 可能是默认添加的，这里不再处理
            if (byId.getFloor() > 1) {
                LambdaUpdateWrapper<CommentHierarchicalStar> subjectStarLambdaUpdateWrapper = Wrappers.<CommentHierarchicalStar>update().lambda().eq(CommentHierarchicalStar::getId, commentHierarchicalStar.getId()).set(CommentHierarchicalStar::getFloor, byId.getStarCount());
                update(subjectStarLambdaUpdateWrapper);
            }
        }

        return commentHierarchicalStar;
    }

    /**
     * 异步处理取消，该方法永远返回 true
     * @param cancelStarParam
     * @return
     */
    @Override
    public boolean cancelStar(CommentHierarchicalCancelStarParam cancelStarParam) {
        executorService.execute(()->{
            log.info("开始取消点赞,commentHierarchicalId={},userId={}",cancelStarParam.getCommentHierarchicalId(),cancelStarParam.getOwnerUserId());
            boolean remove = remove(Wrappers.<CommentHierarchicalStar>lambdaQuery()
                    .eq(CommentHierarchicalStar::getCommentHierarchicalId, cancelStarParam.getCommentHierarchicalId())
                    .eq(CommentHierarchicalStar::getOwnerUserId, cancelStarParam.getOwnerUserId())
            );
            if (remove) {
                // 取消成功后，点赞数减 1
                iCommentHierarchicalService.plusForColumnById(cancelStarParam.getCommentHierarchicalId(), CommentHierarchical::getStarCount,-1);
            }else {
                log.error("取消点赞失败，因为删除点赞返回false，这将导致层级 点赞数不会减1");
            }
            log.info("取消点赞结束,commentHierarchicalId={},userId={}",cancelStarParam.getCommentHierarchicalId(),cancelStarParam.getOwnerUserId());

        });
        return true;
    }

    @Override
    public Map<String, Page<CommentHierarchicalStar>> listLatestStarForPerCommentHierarchical(List<String> commentSubjectIds, Integer count) {
        Assert.notEmpty(commentSubjectIds,"commentSubjectIds 不能为空");
        Assert.notNull(count,"count 不能为空");


        Map<String,Page<CommentHierarchicalStar>> result = new HashMap<>();

        CompletableFuture[] completableFutures = commentSubjectIds.stream().map(commentSubjectId -> CompletableFuture.supplyAsync(() -> {
            // 我嚓，这个 page 不能提出来，否则得到的数据会是一样的
            Page page = convertPage(new BasePageQueryForm().setCurrent(1L).setSize(Integer.toUnsignedLong(count)));
            page.setSearchCount(false);
            Page page1 = page(page, Wrappers.<CommentHierarchicalStar>lambdaQuery().eq(CommentHierarchicalStar::getCommentHierarchicalId, commentSubjectId).orderByDesc(CommentHierarchicalStar::getTimeAt));
            return page1;
        }, executorService).whenComplete((r,e)->{result.put(commentSubjectId, (Page<CommentHierarchicalStar>)r);})).toArray(CompletableFuture[]::new);
        CompletableFuture.allOf(completableFutures).join();
        return result;
    }
}
